#ifndef UCGRAPHICS_H
#define UCGRAPHICS_H

#ifndef UCVECTOR_H
class vector;         // use a forwared declaration for vector class
#endif

#ifndef UCMATRIX_H
class matrix;         // use a forwared declaration for matrix class
#endif

#ifndef UCCONTOUR_H
class UCcontour;
#endif

//
//  enumerated types associated with parameters
//

//   For the next two enums the first word of the enumerated constant
//     refers to the x axis and the second to the y axis.  For example,
//     LIN_LOG refers to a linear scale on the x axis and logrithmic
//     scale on the y axis, while LOG_LIN is just the opposite.
//      
//   These are used with variable scale_type
enum {LIN_LIN = 1, LIN_LOG, LOG_LIN, LOG_LOG};

//   These are used with variable axis_type.  Again of form x_y.
//     Grid refers to line drawn across plot, perimeter draws axis
//     at the edge of the plot, and floating draws the axis on the 
//     graph intersecting at the point given by x_axis and y_axis
enum {GRID_GRID = 0, GRID_PERIMETER, GRID_FLOATING, PERIMETER_GRID = 4,
      PERIMETER_PERIMETER, PERIMETER_FLOATING, FLOATING_GRID = 8,
      FLOATING_PERIMETER, FLOATING_FLOATING};


enum {AUTO, AUTO_OFF};

#ifndef SCIENTIFIC
#define SCIENTIFIC 1
#endif
#ifndef FLOATING_POINT
#define FLOATING_POINT 0
#endif

#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif


//**********************************************************************
//
//    CLASS UCSYMBOL           
//
//**********************************************************************

#ifndef UCSYMBOL_H
#define UCSYMBOL_H

class UCsymbol
{
  public:
    long int_value;

      // Constructors
    UCsymbol(long l) { int_value = l;}
    UCsymbol(int i) { int_value = i;}


    operator long() const {return int_value;}
    int operator==(const UCsymbol& s) const
       {return (int_value == s.int_value);}
    int operator==(long s) const
       {return (int_value == s);}
    friend int operator==(long s, const UCsymbol t)
       {return (s == t.int_value);}
};

//enum {CURVE = 1, POINTS, CURVE_AND_POINTS};

extern const UCsymbol NULL_UCSYMBOL;

extern const UCsymbol CURVE;
extern const UCsymbol POINTS;
extern const UCsymbol CURVE_AND_POINTS;

#endif

//**********************************************************************
//
//    STRUCTURE GRAPHICS_INIT
//
//**********************************************************************

typedef struct{
    float frame_l;
    float frame_r;
    float frame_b;
    float frame_t;
    long contour_scaling;
    float xmin;
    float xmax;
    float ymin;
    float ymax;
    long  majorx;
    long  majory;
    long  minorx;
    long  minory;
    long  scale_type;
    long  label_type;
    long  label_field;
    long  precision;
    long  char_size;
    long  x_label;
    long  y_label;
    long  axis_type;
    float x_intercept;
    float y_intercept;
    long  plot_style;
    long  point_type;
    float horiz_ang;
    float vert_ang;

} graphics_init;



//
//**********************************************************************
//               UCGRAPHICS.H  -  CLASS GRAPHICS HEADER FILE
//**********************************************************************
//
//   The class graphics consists of only static members
//


class graphics
{
private:
// the private members will be certain format variables and such


    // state flags
     static long opened;    // True if open has been called 

     static long autoflag;  // If true routines do auto scaling
     static long firstplot; // True when graphics are opened and
                            //   after frame is called.  False
                            //   after a call to plot.

                            // The two flags autoflag and firstplot
                            //   are used to determine whether or not
                            //   to draw the axis and labels


       // portion of window for plot frame
     static float frame_l;
     static float frame_r;
     static float frame_b;
     static float frame_t;



      // Subplot Variables
     static long subplot_flag;       // flag for subplot mode
     static long subplot_rows;       // # of rows
     static long subplot_columns;    // # of columns
     static long subplot_row;        // The row presently being plotted to
     static long subplot_column;     //  "  column  "       "      "     "
     static long *subplot_firstplot; // array of flags - work the same 
                                     //   firstplot
     static float *subplot_xmin;     // Saved ranges for the subplots
     static float *subplot_xmax;
     static float *subplot_ymin;
     static float *subplot_ymax;

       //  Hold frame variable while in subplot mode so that a 
       //    call to subplot_off will restore the frame coordinate
       //    to the values they held prior to the subplot_on call.
     static float frame_l_temp;
     static float frame_r_temp;
     static float frame_b_temp;
     static float frame_t_temp;

     static long contour_scaling;   // Flag that if on coutour routines
                                     //  minipulate frame so that ticks
                                     //  are evenly spaced.  If off contour
                                     //  fills whole area defined by 
                                     //  frame_l, etc.

       // * * *  For 2d Plots  * * * 

       //  Range for plot set by a call to axis or to a call to a
       //    plotting function when autoflag is on.
     static float xmin;
     static float xmax; 
     static float ymin;
     static float ymax;


       // for tick marks on axis
     static long majorx;    // # of major ticks - the ones that get
     static long majory;    //    labeled
     static long minorx;    // # of minor ticks in between major ticks
     static long minory;

       //
     static long scale_type; // sets log or linear map - see above enum

           
     static long label_type;  // either SCIENTIFIC or FLOATING_POINT
     static long label_field; // width of the label field
     static long precision;   // number of spaces after decimal point
     static long char_size;   // size of char in screen pixels


     static long x_label;   // controls writing of labels
     static long y_label;   /* -1 = no axis or labels
                                0 = axis without labels
                                1 = axis with labels      */


     static long axis_type; // Hold type of axis to be drawn.  Set to
                            //   value from enumerated constant above

     static float x_intercept;   // where to draw axis when axis_type is
     static float y_intercept;   //   set to a value that has one axis as
                                 //   floating, e.g. axis_type = GRID_FLOATING


     static long plot_style; // CURVE, POINTS, CURVE_AND_POINTS
     static long point_type; // char to be plotted as a point
                            //   0 default, point plotted
                            //   - ncar polymark -pointtype used
                            //   + char char(pointype) used
// 
// format vars for surface plot
//
     static float horiz_ang;// angle in degrees to the line of sight
                            //   in X-Y plain from pos X axis
     static float vert_ang; // angle in degrees up from X-Y plain

public:
//
// functions for changing data mambers
//
     static void turn_off_contour_scaling(){contour_scaling = FALSE;}
     static void turn_on_contour_scaling(){contour_scaling = TRUE;}


     static void set_frame(float fl, float fr, float fb, float ft);

     static void set_ticks(long majrx, long minrx, long majry, long minry)
         {majorx = majrx; minorx = minrx; majory = majry; minory = minry;}
     static void set_x_ticks(long majr, long minr)
         {majorx = majr; minorx = minr;}
     static void set_y_ticks(long majr, long minr)
         {majory = majr; minory = minr;}

     static void set_scale(long type)
         { if (type >= 1 && type <= 4) scale_type = type;}

  //
  //  Control axis and label modes
  //
     static void set_label_type(long type)
         {if (type == SCIENTIFIC)  
            label_type = SCIENTIFIC;
          else
            label_type = FLOATING_POINT;}
     static void set_label_format(long field, long prec)
         {label_field = field; precision = prec;}

     static void set_char_size(long size)
         {char_size = size;}

     static void turn_off_y_labels() {if (y_label == 1) y_label = 0;}
     static void turn_off_x_labels() {if (x_label == 1) x_label = 0;}
     static void turn_off_labels()
         {turn_off_y_labels(); turn_off_x_labels();}

     static void turn_on_y_labels() { y_label = 1;}
     static void turn_on_x_labels() { x_label = 1;}
     static void turn_on_labels() { y_label = x_label = 1;}

     static void turn_off_y_axis() {y_label = -1;}
     static void turn_off_x_axis() {x_label = -1;}
     static void turn_off_axis() {y_label = x_label = -1;}

     static void turn_on_y_axis() {if (y_label == -1) y_label = 0;}
     static void turn_on_x_axis() {if (y_label == -1) y_label = 0;}
     static void turn_on_axis(){turn_on_y_axis(); turn_on_x_axis();}


     static void set_axis_type(long t);

     static void set_intercepts(float x, float y)
         {x_intercept = x; y_intercept = y;}

//
// Control plotstyle
//
     static void set_plot_style(long p)
         {if (p >= 1 && p <= 3) plot_style = p;}
     static void set_point_style(long p) 
         {if (p >= -5) point_type = p;}

//
// Control angle for surface plot
//
     static void set_horizontal_angle(float ang)
         {horiz_ang = ang;}
     static void set_vertical_angle(float ang)
         {vert_ang = ang;}


//
// general system function
//
     static void open();
     static void open(graphics_init &init);
     static void close();
     static void frame();

     static void axis(float xmn, float xmx, float ymn, float ymx);
     static void axis(long flag)
        {if (flag == AUTO || flag == AUTO_OFF) autoflag = flag;}

     static void title(char *);
     static void label_x(char *);
     static void label_y(char *,long side = 0);
     static void draw_string(float,float,char *,float,float,float);
//
// plotting functions
//
     friend void matrix::contour() const;
             
             // Sepcify # of lines
     friend void matrix::contour(long nlines) const;  
     friend void matrix::contour(int nlines) const;

             // Specify # of lines between low and hi
     friend void matrix::contour(long nlines, double low, double hi) const; 
     friend void matrix::contour(int nlines, double low, double hi) const; 

             // Specify low and hi
     friend void matrix::contour(double low, double hi) const; 

             // Sepcify line increment
     friend void matrix::contour(float inc) const;  
     friend void matrix::contour(double inc) const;  

             // Specify increment between low and hi
     friend void matrix::contour(float inc, double low, double hi) const;
     friend void matrix::contour(double inc, double low, double hi) const;

             // Pass array of line values
     friend void matrix::contour(double* values, long nlines) const;
     friend void matrix::contour(float* values, long nlines) const;
     friend void matrix::contour(vector &vec) const;

             // Pass contour class
     friend void matrix::contour(UCcontour &cont) const;


     friend void matrix::surface() const;
     friend void matrix::surface(float hang, float vang) const;


     friend void matrix::plot(const UCsymbol style, long point_style) const;
     friend void matrix::plot(long point_style) const;

     friend void matrix::plot(vector &vec, const UCsymbol style, 
                              long point_style) const;
     friend void matrix::plot(vector &vec, long point_style) const;

     friend void matrix::plot(matrix &mat, const UCsymbol style, 
                              long point_style) const;
     friend void matrix::plot(matrix &mat, long point_style) const;

//
//  VECTOR ROUTINES
//
     friend void vector::plot(const UCsymbol style, long point_style) const;
     friend void vector::plot(long style) const;

     friend void vector::plot(vector &vec, const UCsymbol style, 
                              long point_style) const;
     friend void vector::plot(vector &vec, long style) const;


//
//  PLOTTING ROUTINES FOR FUNCTIONS
//
     static void plot(double (*f)(double), double xmin, double xmax, 
                const UCsymbol style = NULL_UCSYMBOL, long point_style = 0);
     static void plot(double (*f)(double), double xmin, double xmax, 
                      long style);

     static void plot(double (*f)(double), 
                const UCsymbol style = NULL_UCSYMBOL, long point_style = 0);
     static void plot(double (*f)(double), long style);

//
//  The code for subplots
//
     static void subplot_on(long rows, long columns);

     static void subplot(long row, long column);

     static void subplot_off();

//
//  The following functions are used by the routines above
//
    friend long* ucg_get_long_array(long size);
    friend float* ucg_get_float_array(long size);
    friend void ucg_double_2_float(double* darray, float* farray, 
                     long size, float &min, float &max);
    friend void ucg_double_2_float(double* darray,
                                   float* farray, long size);
    friend void ucg_get_min_max(float * farray, long num, 
                                float &min, float &max);
    friend void ucg_get_min_max(double *darray, long num,
                                float &min, float &max);
    friend void ucg_set_array_to_index(float * farray, long size,
                                       long start);
    friend void ucg_plot(float *x, float *y, long size, 
                         const UCsymbol plot_style, long point_style);
    friend void ucg_det_tic_marks(long num, long &majr, long &minr);
    friend void ucg_setup();
    friend void ucg_det_cont_frame(float &fl, float &fr, float &fb,
                                   float &ft, long rows, long columns);
};




//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
//    class UCcontour 
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
//**********************************************************************
//**********************************************************************
//
//  This file contains the class definition of a simple class for 
//    drawing contours.  I developed it to simplify the ucgraphics
//    files.  It will also eliminate ucgraphics having code for both
//    unix and dos, since the .c file associated with this will deal
//    with what system we're on.
//
//**********************************************************************
//**********************************************************************

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif




class UCcontour{
  private:
    long nlines;     // # of lines - if 0 routine will pick # of lines

    double line_spacing; // Spacing to use between lines.  Only used
                          //  if non-zero and nlines = 0.  If hi>low
                          //  lines will have values low+k*line_spacing
                          //  where k is an integer.  If hi<=low then
                          //  lines will have values k*line_spacing

    double hi;           // If hi>low then only contour lines between
    double low;          //  hi and low are drawn.

    double* line_values; // Array of nlines elements holding the values
                         //  of the contour lines.  If null, routine
                         //  uses evenly spaced lines.

       //  Here will be other arrays that will control extras such as
       //   label info, dash pattern, color, etc.
    long* color;         // The array holding the color of each line
    long* label;         // What to do with line:
                         /*       0 - nothing drawn
                                  1 - draw line without labels
                                  2 - draw labels without lines
                                  3 - draw both  */

    double frame_l;       // The portion of the frame to plot in
    double frame_r;
    double frame_b;
    double frame_t;

    long hi_low_label_flag;  // if true draw hi_low labels
    long background_flag;    // if true draw background


  public:

     // Constructor and destructor
    UCcontour();
    UCcontour(long nl);
    UCcontour(long nl, double* values);
    ~UCcontour();

        // Other functions
    void set_number_of_lines(long num);
 
    void set_line_spacing(double inc){line_spacing = inc;}

    void set_low_hi(double l, double h){ low = l; hi = h;}

    void set_line_value(long line, double value);
    void set_line(long line, double value, long col, long flag);
    void set_line_color(long line, long col);
    void set_line_label_flag(long line, long flag);

    void set_frame(double, double, double, double);

    void turn_on_hi_low_labels(){hi_low_label_flag = TRUE;}
    void turn_off_hi_low_labels(){hi_low_label_flag = FALSE;}

    void turn_on_background(){background_flag = TRUE;}
    void turn_off_background(){background_flag = FALSE;}


      // drawing routines
    void draw_contour_lines(double* A, long n, long m);

      // helper functions
    void ucc_contour(double*,double*,double*,double*,int,int,int);
    void ucc_draw_background(long rows, long columns);  // dos only
    //void ucc_draw_hi_low_labels(double *A, long rows, long columns);

    double* ucc_get_double_array(long length);
    void ucc_get_min_max(double*,long,double&,double&);

};


#endif
